using Rogan.Data.MsAccess;
using Rogan.Data.Oracle;
using Rogan.Data.SqlServer;
using Rogan.Data.SqlServer9;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Reflection;
using Rogan.Utility.Common;

namespace Rogan.Data
{
	public static class ProviderFactory
	{
		private static readonly Dictionary<string, DbProvider> ProviderCache = new Dictionary<string, DbProvider>();
		public static DbProvider Default
		{
			get
			{
				DbProvider result;
				try
				{
					if (ConfigurationManager.ConnectionStrings.Count > 0)
					{
						ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[ConfigurationManager.ConnectionStrings.Count - 1];
						string[] array = connectionStringSettings.ProviderName.Split(new[]
						{
							','
						});
						DbProvider dbProvider;
						if (array.Length > 1)
						{
							dbProvider = CreateDbProvider(array[1].Trim(), array[0].Trim(), connectionStringSettings.ConnectionString);
						}
						else
						{
							dbProvider = CreateDbProvider(null, array[0].Trim(), connectionStringSettings.ConnectionString);
						}
						dbProvider.ConnectionStringsName = connectionStringSettings.Name;
						result = dbProvider;
					}
					else
					{
						result = null;
					}
				}
				catch
				{
					result = null;
				}
				return result;
			}
		}

	    public static DbProvider CreateDbProvider(string assemblyName, string className, string connectionString)
		{
			Guard.IsNotNullOrEmpty(connectionString, "connectionString");
			if (connectionString.IndexOf("microsoft.jet.oledb", StringComparison.OrdinalIgnoreCase) > -1 || connectionString.IndexOf(".db3", StringComparison.OrdinalIgnoreCase) > -1)
			{
				Guard.Check(connectionString.IndexOf("data source", StringComparison.OrdinalIgnoreCase) > -1, "ConnectionString的格式有错误，请检查");
				string text = connectionString.Substring(connectionString.IndexOf("data source", StringComparison.OrdinalIgnoreCase) + "data source".Length + 1).TrimStart(new[]
				{
					' ',
					'='
				});
				if (text.ToLower().StartsWith("|datadirectory|"))
				{
					text = AppDomain.CurrentDomain.BaseDirectory.TrimEnd(new[]
					{
						'\\'
					}) + "\\App_Data" + text.Substring("|datadirectory|".Length);
				}
				else
				{
					if (connectionString.StartsWith("./") || connectionString.EndsWith(".\\"))
					{
						connectionString = connectionString.Replace("/", "\\").Replace(".\\", AppDomain.CurrentDomain.BaseDirectory.TrimEnd(new[]
						{
							'\\'
						}) + "\\");
					}
				}
				connectionString = connectionString.Substring(0, connectionString.ToLower().IndexOf("data source")) + "Data Source=" + text;
			}
			if (connectionString.Contains("~/") || connectionString.Contains("~\\"))
			{
				connectionString = connectionString.Replace("/", "\\").Replace("~\\", AppDomain.CurrentDomain.BaseDirectory.TrimEnd(new[]
				{
					'\\'
				}) + "\\");
			}
			if (string.IsNullOrEmpty(className))
			{
				className = typeof(SqlServerProvider).ToString();
			}
			else
			{
				if (string.Compare(className, "System.Data.SqlClient", true) == 0 || string.Compare(className, "Rogan.Data.SqlServer", true) == 0)
				{
					className = typeof(SqlServerProvider).ToString();
				}
				else
				{
					if (string.Compare(className, "Rogan.Data.SqlServer9", true) == 0 || className.IndexOf("SqlServer9", StringComparison.OrdinalIgnoreCase) >= 0 || className.IndexOf("sqlserver2005", StringComparison.OrdinalIgnoreCase) >= 0 || className.IndexOf("sql2005", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						className = typeof(SqlServer9Provider).ToString();
					}
					else
					{
						if (className.IndexOf("oracle", StringComparison.OrdinalIgnoreCase) >= 0)
						{
							className = typeof(OracleProvider).ToString();
						}
						else
						{
							if (className.IndexOf("access", StringComparison.OrdinalIgnoreCase) >= 0)
							{
								className = typeof(MsAccessProvider).ToString();
							}
							else
							{
								if (className.IndexOf("mysql", StringComparison.OrdinalIgnoreCase) >= 0)
								{
									className = "Rogan.Data.MySql.MySqlProvider";
									assemblyName = "Rogan.Data.MySql";
								}
								else
								{
									if (className.IndexOf("sqlite", StringComparison.OrdinalIgnoreCase) >= 0)
									{
										className = "Rogan.Data.Sqlite.SqliteProvider";
										assemblyName = "Rogan.Data.Sqlite";
									}
								}
							}
						}
					}
				}
			}
			string key = assemblyName + className + connectionString;
			if (ProviderCache.ContainsKey(key))
			{
				return ProviderCache[key];
			}
			Assembly assembly;
			if (assemblyName == null)
			{
				assembly = typeof(DbProvider).Assembly;
			}
			else
			{
				assembly = Assembly.Load(assemblyName);
			}
			DbProvider dbProvider = assembly.CreateInstance(className, false, BindingFlags.Default, null, new object[]
			{
				connectionString
			}, null, null) as DbProvider;
			ProviderCache.Add(key, dbProvider);
			return dbProvider;
		}
		public static DbProvider CreateDbProvider(string connStrName)
		{
			Guard.IsNotNullOrEmpty(connStrName, "connStrName");
			ConnectionStringSettings connectionStringSettings = ConfigurationManager.ConnectionStrings[connStrName];
			Guard.Check(connectionStringSettings != null, "在配置文件中找不到名字为 " + connStrName + " 的ConnectionString 节点");
			string[] array = connectionStringSettings.ProviderName.Split(new[]
			{
				','
			});
			DbProvider dbProvider;
			if (array.Length > 1)
			{
				dbProvider = CreateDbProvider(array[0].Trim(), array[1].Trim(), connectionStringSettings.ConnectionString);
			}
			else
			{
				dbProvider = CreateDbProvider(null, array[0].Trim(), connectionStringSettings.ConnectionString);
			}
			dbProvider.ConnectionStringsName = connStrName;
			return dbProvider;
		}
	}
}
